# 示例10 - 使用Quartz插件

说明

此示例演示XML作业初始化插件以及历史记录插件的使用。

# SimpleJob.java源码

package org.quartz.examples.example10;

import java.util.Date;
import java.util.Set;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 这只是被例1执行过许多次的简单作业(只改了一下输出信息)
 * 作者:Bill Kratzer
 */
public class SimpleJob implements Job {

    private static Logger _log = LoggerFactory.getLogger(SimpleJob.class);

    /**
     * 作业初始化的空参构造函数
     */
    public SimpleJob() {
    }

    /**
     * 当与此作业相关联的触发器触发时,由调度器调用此方法
     * Throws:作业执行异常(JobExecutionException)-当执行作业时产生异常
     */
    @SuppressWarnings("unchecked")
    public void execute(JobExecutionContext context)
        throws JobExecutionException {

        //此作业简单地输出它的名称及运行时间
        JobKey jobKey = context.getJobDetail().getKey();
        _log.info("Executing job: " + jobKey + " executing at " + new Date() + ", fired by: " + context.getTrigger().getKey());
        
        if(context.getMergedJobDataMap().size() > 0) {
            Set<String> keys = context.getMergedJobDataMap().keySet();
            for(String key: keys) {
                String val = context.getMergedJobDataMap().getString(key);
                _log.info(" - jobDataMap entry: " + key + " = " + val);
            }
        }
        
        context.setResult("hello");
    }

}

# PlugInExample.java源码

package org.quartz.examples.example10;

import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SchedulerMetaData;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 此示例将产生大量要运行的作业
 * 作者:James House, Bill Kratzer
 */
public class PlugInExample {

  public void run() throws Exception {
    Logger log = LoggerFactory.getLogger(PlugInExample.class);

    //首先,我们必须获得对调度器的引用
    SchedulerFactory sf = new StdSchedulerFactory();
    Scheduler sched = null;
    try {
      sched = sf.getScheduler();
    } catch (NoClassDefFoundError e) {
      log.error(" Unable to load a class - most likely you do not have jta.jar on the classpath. If not present in the examples/lib folder, please " +
                "add it there for this sample to run.", e);
      return;
    }

    log.info("------- Initialization Complete -----------");

    log.info("------- (Not Scheduling any Jobs - relying on XML definitions --");

    log.info("------- Starting Scheduler ----------------");

    //开启调度器
    sched.start();

    log.info("------- Started Scheduler -----------------");

    log.info("------- Waiting five minutes... -----------");

    //等待5分钟让我们的作业有机会执行
    try {
      Thread.sleep(300L * 1000L);
    } catch (Exception e) {
      //
    }

    //关闭调度器
    log.info("------- Shutting Down ---------------------");
    sched.shutdown(true);
    log.info("------- Shutdown Complete -----------------");

    SchedulerMetaData metaData = sched.getMetaData();
    log.info("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");
  }

  public static void main(String[] args) throws Exception {

    PlugInExample example = new PlugInExample();
    example.run();
  }

}

# 配置文件

本示例需要 quartz.propertiesquartz_data.xml 配置文件,它们位于 examples/example10 目录中。

# quartz.properties

#============================================================================
# 配置主调度器属性
#============================================================================

org.quartz.scheduler.instanceName: TestScheduler
org.quartz.scheduler.instanceId: AUTO

#============================================================================
# 配置线程池
#============================================================================

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 3
org.quartz.threadPool.threadPriority: 5

#============================================================================
# 配置JobStore
#============================================================================

org.quartz.jobStore.misfireThreshold: 60000

org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore

#============================================================================
# 配置插件
#============================================================================

org.quartz.plugin.triggHistory.class: org.quartz.plugins.history.LoggingJobHistoryPlugin

org.quartz.plugin.jobInitializer.class: org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames: quartz_data.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound: true
org.quartz.plugin.jobInitializer.scanInterval: 120
org.quartz.plugin.jobInitializer.wrapInUserTransaction: false

该配置文件的关键配置说明:

  • 线程池:配置了3个线程
  • LoggingJobHistoryPlugin:历史记录插件,用于记录作业的执行历史
  • XMLSchedulingDataProcessorPlugin:XML作业初始化插件,从 quartz_data.xml 文件中加载作业和触发器定义

# quartz_data.xml

<?xml version="1.0" encoding="UTF-8"?>
<job-scheduling-data xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd"
    version="1.8">

    <pre-processing-commands>
        <delete-jobs-in-group>*</delete-jobs-in-group>  <!-- 清除调度器中的所有作业 -->
        <delete-triggers-in-group>*</delete-triggers-in-group> <!-- 清除调度器中的所有触发器 -->
    </pre-processing-commands>

    <processing-directives>
        <!-- 如果调度器中存在与此文件中同名的作业/触发器,则覆盖它们 -->
        <overwrite-existing-data>true</overwrite-existing-data>
        <!-- 如果调度器中存在与此文件中同名的作业/触发器,且覆盖为false,则忽略它们而不是产生错误 -->
        <ignore-duplicates>false</ignore-duplicates>
    </processing-directives>

    <schedule>
	    <job>
	        <name>TestJob1</name>
	        <job-class>org.quartz.examples.example10.SimpleJob</job-class>
	    </job>

        <job>
            <name>TestDurableJob</name>
            <job-class>org.quartz.examples.example10.SimpleJob</job-class>
            <durability>true</durability>
            <recover>false</recover>
        </job>

	    <trigger>
	        <simple>
	            <name>TestSimpleTrigger1AtFiveSecondInterval</name>
	            <job-name>TestJob1</job-name>
	            <repeat-count>-1</repeat-count> <!-- 无限重复  -->
	            <repeat-interval>5000</repeat-interval>  <!--  每5秒 -->
	        </simple>
	    </trigger>

	    <job>
	        <name>TestJob2</name>
	        <group>GroupOfTestJob2</group>
	        <description>This is the description of TestJob2</description>
	        <job-class>org.quartz.examples.example10.SimpleJob</job-class>
	        <durability>false</durability>
	        <recover>true</recover>
	        <job-data-map>
	            <entry>
	                <key>someKey</key>
	                <value>someValue</value>
	            </entry>
	            <entry>
	                <key>someOtherKey</key>
	                <value>someOtherValue</value>
	            </entry>
	        </job-data-map>
	    </job>

	    <trigger>
	        <simple>
	            <name>TestSimpleTrigger2AtTenSecondIntervalAndFiveRepeats</name>
	            <group>GroupOfTestJob2Triggers</group>
	            <job-name>TestJob2</job-name>
	            <job-group>GroupOfTestJob2</job-group>
	            <start-time>2010-02-09T10:15:00</start-time>
	            <misfire-instruction>MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT</misfire-instruction>
	            <repeat-count>5</repeat-count>
	            <repeat-interval>10000</repeat-interval>
	        </simple>
	    </trigger>

	    <trigger>
	        <cron>
	            <name>TestCronTrigger2AtEveryMinute</name>
	            <group>GroupOfTestJob2Triggers</group>
	            <job-name>TestJob2</job-name>
	            <job-group>GroupOfTestJob2</job-group>
                <job-data-map>
                    <entry>
                        <key>someKey</key>
                        <value>overriddenValue</value>
                    </entry>
                    <entry>
                        <key>someOtherKey</key>
                        <value>someOtherOverriddenValue</value>
                    </entry>
                </job-data-map>
                <cron-expression>0 * * ? * *</cron-expression>
	        </cron>
	    </trigger>

	    <trigger>
	        <cron>
	            <name>TestCronTrigger2AtEveryMinuteOnThe45thSecond</name>
	            <group>GroupOfTestJob2Triggers</group>
	            <job-name>TestJob2</job-name>
	            <job-group>GroupOfTestJob2</job-group>
	            <start-time>2010-02-09T12:26:00.0</start-time>
	            <end-time>2012-02-09T12:26:00.0</end-time>
	            <misfire-instruction>MISFIRE_INSTRUCTION_SMART_POLICY</misfire-instruction>
	            <cron-expression>45 * * ? * *</cron-expression>
	            <time-zone>America/Los_Angeles</time-zone>
	        </cron>
	    </trigger>
    </schedule>
</job-scheduling-data>

该XML文件定义了以下内容:

  • TestJob1:绑定一个SimpleTrigger,每5秒执行一次,无限重复
  • TestDurableJob:一个持久化的作业(没有关联触发器)
  • TestJob2:绑定三个触发器:
    • 一个SimpleTrigger,每10秒执行一次,重复5次
    • 一个CronTrigger,每分钟执行一次(0 * * ? * *
    • 一个CronTrigger,每分钟的45秒执行一次(45 * * ? * *

# 控制台输出

[main] INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
[main] INFO org.quartz.simpl.SimpleThreadPool - Job execution threads will use class loader of thread: main
[main] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.3.0 created.
[main] INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized.
[main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.0
[main] INFO org.quartz.examples.example10.PlugInExample - ------- Initialization Complete -----------
[main] INFO org.quartz.examples.example10.PlugInExample - ------- (Not Scheduling any Jobs - relying on XML definitions --
[main] INFO org.quartz.examples.example10.PlugInExample - ------- Starting Scheduler ----------------
[main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
[main] INFO org.quartz.examples.example10.PlugInExample - ------- Started Scheduler -----------------
[main] INFO org.quartz.examples.example10.PlugInExample - ------- Waiting five minutes... -----------
[main] INFO org.quartz.examples.example10.PlugInExample - ------- Shutting Down ---------------------
[main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down.
[main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused.
[main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete.
[main] INFO org.quartz.examples.example10.PlugInExample - ------- Shutdown Complete -----------------
[main] INFO org.quartz.examples.example10.PlugInExample - Executed 0 jobs.

Process finished with exit code 0

微信公众号

QQ交流群
原创网站开发,偏差难以避免。

如若发现错误,诚心感谢反馈。

愿你倾心相念,愿你学有所成。

愿你朝华相顾,愿你前程似锦。